module frv_store_entry (
    input clk,    // Clock
    input clk_en, // Clock Enable
    input rst_n,  // Asynchronous reset active low
    //queue ctrl
    input               selected_in,
    input               selected_out,
    input               queue_forward,
    input               selected_WAW,
    input               retire_vld,
    input               cache_selected,
    input               cache_miss,
    input               cache_hit,
    input               ddr_selected,
    input               ddr_ack,
    input               dev_selected,
    input               flush_selected,
    input               resp_selected,
    input               load_resp,
    //dev axi lite
    input               dev_store_awready,
    input               dev_store_wready,
    input               dev_store_bvalid,
    //items
    input[32-1:0]              entry_req_addr,
    input[5+1-1:0] entry_req_id,
    input[1-1:0]               entry_vld,
    input[4-1:0]               entry_req_state,
    input[1-1:0]               entry_req_type,
    input[32-1:0]              entry_store_data,
    input                      entry_store_tag,
    input[3-1:0]               entry_req_info,

    output[32-1:0]               entry_req_addr_o,
    output[5+1-1:0]  entry_req_id_o,
    output[1-1:0]                entry_vld_o,
    output[4-1:0]                entry_req_state_o,
    output[1-1:0]                entry_req_type_o,
    output[32-1:0]               entry_store_data_o,
    output                       entry_store_tag_o,
    output[3-1:0]                entry_req_info_o


);
//states
`define STORE_EMPTY   0 
`define STORE_WAIT    1 
`define STORE_RETIRE  2 
`define STORE_MEM_ACCESSED   3 
`define STORE_DEV_ACCESSED   4 

`define STORE_CACHE_MISS    5 
`define STORE_DDR_ACCESSED     6 
`define STORE_DEV_AWREADY 7
`define STORE_DEV_WREADY 8
`define STORE_DEV_READY 9
`define STORE_RESP 10
`define WAIT_RETIRE 11
wire  entry_req_addr_en         =   selected_in|queue_forward;
wire  entry_req_id_en           =   selected_in|queue_forward;
wire  entry_vld_en              =   selected_in|queue_forward;
wire  entry_req_type_en         =   selected_in|queue_forward;
wire  entry_store_data_en       =   selected_in|queue_forward;
wire  entry_store_tag_en        =   selected_WAW;
wire  entry_req_info_en         =   selected_in|queue_forward;




dffr #(.DW(32))              entry_req_addr_ff                    (clk,rst_n,entry_req_addr_en      ,entry_req_addr      ,entry_req_addr_o);
dffr #(.DW(5+1)) entry_req_id_ff                      (clk,rst_n,entry_req_id_en        ,entry_req_id        ,entry_req_id_o);
dffr #(.DW(1))               entry_vld_ff                         (clk,rst_n,entry_vld_en           ,entry_vld           ,entry_vld_o);
dffr #(.DW(1))               entry_req_type_ff                    (clk,rst_n,entry_req_type_en      ,entry_req_type      ,entry_req_type_o);
dffr #(.DW(32))              entry_store_data_ff                  (clk,rst_n,entry_store_data_en    ,entry_store_data    ,entry_store_data_o);
dffr #(.DW(1))               entry_store_tag_ff                   (clk,rst_n,entry_store_tag_en     ,entry_store_tag     ,entry_store_tag_o);
dffr #(.DW(3))               entry_req_info_ff                    (clk,rst_n,entry_req_info_en      ,entry_req_info      ,entry_req_info_o);


logic [4-1:0]           entry_req_state_o_next;
dffr #(.DW(4))               entry_req_state_ff                   (clk,rst_n,1'b1,entry_req_state_o_next,entry_req_state_o);

always_comb begin
    entry_req_state_o_next=entry_req_state_o;
    case (entry_req_state_o)
        `STORE_EMPTY:begin
            entry_req_state_o_next= selected_in   ?`STORE_WAIT:
                                    flush_selected?0:
                                    queue_forward ?entry_req_state:entry_req_state_o;
        end
        `STORE_WAIT:begin
            entry_req_state_o_next= selected_in   ?`STORE_WAIT:
                                    flush_selected?0:
                                    queue_forward ?entry_req_state:
                                    resp_selected ?`STORE_RESP:entry_req_state_o;
        end// to optimize:retire_vld and select in same satate? 
        `STORE_RESP:begin
            entry_req_state_o_next= selected_in   ?`STORE_WAIT:
                                    flush_selected?0:
                                    queue_forward ?entry_req_state:
                                    load_resp     ?entry_req_state_o:`WAIT_RETIRE;
        end
        `WAIT_RETIRE:begin
            entry_req_state_o_next= selected_in   ?`STORE_WAIT:
                                    flush_selected?0:
                                    queue_forward ?entry_req_state:
                                    retire_vld    ?`STORE_RETIRE:entry_req_state_o;
        end
        `STORE_RETIRE:begin
            entry_req_state_o_next= flush_selected?0:
                                    // queue_forward  ?entry_req_state:
                                    cache_selected ?`STORE_MEM_ACCESSED:
                                    dev_selected?`STORE_DEV_ACCESSED:entry_req_state_o;
        end
        `STORE_MEM_ACCESSED:begin
            entry_req_state_o_next= selected_in   ?`STORE_WAIT:
                                    flush_selected?0:
                                    // queue_forward?entry_req_state:
                                    cache_miss   ?`STORE_CACHE_MISS:
                                    cache_hit    ?`STORE_EMPTY:entry_req_state_o;
        end
        `STORE_DEV_ACCESSED:begin //awvalid wvalid
            entry_req_state_o_next= selected_in                           ?`STORE_WAIT:
                                    flush_selected                        ?0:
                                    (dev_store_wready & dev_store_awready)?`STORE_DEV_READY:
                                    dev_store_awready                     ?`STORE_DEV_AWREADY:
                                    dev_store_wready                      ?`STORE_DEV_WREADY:entry_req_state_o;
        end
        `STORE_CACHE_MISS:begin
            entry_req_state_o_next= selected_in   ?`STORE_WAIT:
                                    flush_selected?0:
                                    // queue_forward?entry_req_state:
                                    ddr_selected  ?`STORE_DDR_ACCESSED:entry_req_state_o;
        end
        `STORE_DDR_ACCESSED:begin
            entry_req_state_o_next= selected_in   ?`STORE_WAIT:
                                    flush_selected?0:
                                    // queue_forward?entry_req_state:
                                    ddr_ack       ?`STORE_RETIRE:entry_req_state_o;
        end
        `STORE_DEV_AWREADY:begin
            entry_req_state_o_next= selected_in     ?`STORE_WAIT:
                                    flush_selected  ?0:
                                    dev_store_wready?`STORE_DEV_READY:entry_req_state_o;
        end
        `STORE_DEV_WREADY:begin
            entry_req_state_o_next= selected_in     ?`STORE_WAIT:
                                    flush_selected  ?0:
                                    dev_store_wready?`STORE_DEV_READY:entry_req_state_o;
        end
        `STORE_DEV_READY:begin //bready
            entry_req_state_o_next= selected_in     ?`STORE_WAIT:
                                    flush_selected  ?0:
                                    dev_store_bvalid?`STORE_EMPTY:entry_req_state_o;
        end
    endcase
end




endmodule


